//
//  SKYPageMonitor.m
//  DRPageTracker
//
//  Created by 张二帅 on 2018/5/6.
//

#import "SKYPageTrackerMonitor.h"
#import <objc/runtime.h>
#import "SKYMethodSwizzler.h"
#import "SKYInfoServer.h"
#import "SKYModel.h"
#import "SKYInfoAcquisitionInterface.h"

NSString const* kSKYCurrentPageName = @"";
NSString const* kSKYCurrentPageStartTime = @"";
static NSString * const kSKYPageTrackerModel = @"kSKYPageTrackerModel";

@interface SKYPageTrackerModel()

@end

@implementation SKYPageTrackerModel

+ (instancetype)pageTrackerModelWithPageName:(NSString *)pageName ;{
    SKYPageTrackerModel *model = [[SKYPageTrackerModel alloc] init];
    model.pageName = pageName;
    model.startDate = [NSDate date];
    return model;
}

@end


@implementation SKYPageTrackerMonitor

- (instancetype)init {
    if (self = [super init]) {
        _ignoreTrackPage = [[NSMutableDictionary alloc] init];
    }
    return self;
}

static SKYPageTrackerMonitor *sky_pageTrackerMonitor = nil;
+ (instancetype)sharedInstance {
    static dispatch_once_t once;
    dispatch_once(&once, ^{
        sky_pageTrackerMonitor = [[SKYPageTrackerMonitor alloc] init];
    });
    return sky_pageTrackerMonitor;
}


/**
 页面已经显示调用  记录页面访问时间
 
 @param pageViewController 需记录页面控制器
 */
+ (void)viewDidAppearWithPageViewController:(UIViewController *)pageViewController;{
    UIViewController *viewController = pageViewController;
    SKYPageTrackerModel *trackerModel = [SKYPageTrackerModel pageTrackerModelWithPageName:NSStringFromClass([viewController class])];
    kSKYCurrentPageName = trackerModel.pageName;
    kSKYCurrentPageStartTime = [SKYInfoServer stringFromDate:trackerModel.startDate];
    //上传指定信息
    [SKYInfoAcquisitionInterface sendPageDidAppearWithPageTrackerModel:trackerModel];
    objc_setAssociatedObject(viewController, &kSKYPageTrackerModel, trackerModel, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

/**
 页面将要离开调用  记录页面离开时间 => 算出页面停留时间 => 上报页面统计信息
 
 @param pageViewController 需记录页面控制器
 */
+ (void)viewDidDisappearWithPageViewController:(UIViewController *)pageViewController;{
    UIViewController *viewController = pageViewController;
    id pageTrackerModel = objc_getAssociatedObject(viewController, &kSKYPageTrackerModel);
    if (pageTrackerModel == nil) {
        return;
    }
    SKYPageTrackerModel *model = (SKYPageTrackerModel *)pageTrackerModel;
    model.endDate = [NSDate date];
    model.stayTime = ([model.endDate timeIntervalSince1970] - [model.startDate timeIntervalSince1970]) * 1000;
    //上传指定信息
    [SKYInfoAcquisitionInterface sendPageDidDisappearWithPageTrackerModel:model];
}

@end



@implementation UIViewController (SKYPageTracker)

+ (BOOL)sky_isIgnoreTrackPageName:(NSString *)pageName {
    NSNumber *ignoreTrack = [[SKYPageTrackerMonitor sharedInstance].ignoreTrackPage valueForKey:pageName];
    if ([pageName hasPrefix:@"NS"] || [pageName hasPrefix:@"UI"] || [SKYInfoServer sharedInstance].config.viewPathReportEnabled == NO || (ignoreTrack != nil && [ignoreTrack boolValue])) {
        return YES;
    }
    return NO;
}

+ (void)load {
    static dispatch_once_t SKYPageTracker;
    dispatch_once(&SKYPageTracker, ^{
        //hook方案一： 为了防止与其他组件hook统一方法冲突使用该库进行hook
        [self sky_swizzleInstanceMethod:@selector(viewDidAppear:) withReplacement:^id(SKY_IMP original, __unsafe_unretained Class swizzledClass, SEL selector) {
            return SKYMethodReplacement(void, UIViewController *,BOOL arg) {
                NSString *className = NSStringFromClass([self class]);
                if ([UIViewController sky_isIgnoreTrackPageName:className]) {
                    return;
                }
                [SKYPageTrackerMonitor viewDidAppearWithPageViewController:self];
            };
        }];
        [self sky_swizzleInstanceMethod:@selector(viewDidDisappear:) withReplacement:^id(SKY_IMP original, __unsafe_unretained Class swizzledClass, SEL selector) {
            return SKYMethodReplacement(void, UIViewController *,BOOL arg) {
                NSString *className = NSStringFromClass([self class]);
                if ([UIViewController sky_isIgnoreTrackPageName:className]) {
                    return;
                }
                [SKYPageTrackerMonitor viewDidDisappearWithPageViewController:self];
            };
        }];

//        [self sky_swizzled_swizzleMethod:[self class] originalSelector:@selector(viewDidAppear:) swizzledSelector:@selector(sky_swizzled_viewDidAppear:)];
//        [self sky_swizzled_swizzleMethod:[self class] originalSelector:@selector(viewDidDisappear:) swizzledSelector:@selector(sky_swizzled_viewDidDisappear:)];
    });
}


// hook方案二：若方案一出现问题，可采取方案二进行hook。已经过测试正常
 
//- (void)sky_swizzled_viewDidAppear:(BOOL)animated {
//    NSString *className = NSStringFromClass([self class]);
//    if ([className hasPrefix:@"NS"] || [className hasPrefix:@"UI"]) {
//        [self sky_swizzled_viewDidAppear:animated];
//        return;
//    }
//    [SKYPageTrackerMonitor viewDidAppearWithPageViewController:self];
//    [self sky_swizzled_viewDidAppear:animated];
//}
//
//- (void)sky_swizzled_viewDidDisappear:(BOOL)animated {
//    NSString *className = NSStringFromClass([self class]);
//    if ([className hasPrefix:@"NS"] || [className hasPrefix:@"UI"]) {
//        [self sky_swizzled_viewDidDisappear:animated];
//        return;
//    }
//    [SKYPageTrackerMonitor viewDidDisappearWithPageViewController:self];
//    [self sky_swizzled_viewDidDisappear:animated];
//}
//
//+ (void)sky_swizzled_swizzleMethod:(Class)cls originalSelector:(SEL)originalSel swizzledSelector:(SEL)swizzledSel {
//    Class class = cls;
//    SEL originalSelector = originalSel;
//    SEL swizzledSelector = swizzledSel;
//
//    Method originalMethod = class_getInstanceMethod(class, originalSelector);
//    Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);
//
//    BOOL success = class_addMethod(class, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod));
//    if (success) {
//        class_replaceMethod(class, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));
//    } else {
//        method_exchangeImplementations(originalMethod, swizzledMethod);
//    }
//}



@end





